﻿using System;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;
using SimpleServiceBus.Messages.Management.Monitoring;
using SimpleServiceBus.Persistence.NHibernate;
using SimpleServiceBus.Persistence.Domain.Management.Entities;
using SimpleServiceBus.Persistence.NHibernate.Repositories;

namespace SimpleServiceBus.Tests.Persistence.NHibernate
{
    [TestFixture, Explicit]
    public class EntityPersistenceTestFixture
    {

        [TestFixtureSetUp]
        public void FixtureSetUp()
        {
            DataSessionManager.Create<ThreadStaticSession>();
            ((DataSessionManager)DataSessionManager.Current).CreateSchema();
        }

        [TestFixtureTearDown]
        public void FixtureTearDown()
        {
            if (DataSessionManager.Current != null)
                DataSessionManager.Current.Dispose();
        }

        [SetUp]
        public void TestSetUp()
        {
            DataSessionManager.Current.RecycleCurrentSession();
        }

        [TearDown]
        public void TearDown()
        {
            if (DataSessionManager.Current.CurrentSession != null)
                DataSessionManager.Current.CurrentSession.Flush();
        }

        [Test]
        public void CanPersistNewManagedEndpoint()
        {
            var ep = CreateNewEndpoint("EPID");

            var repo = new Repository<ManagedEndpoint>();
            repo.SaveOrUpdate(ep);


            try
            {
                int ep_id = ep.Id;
                DataSessionManager.Current.RecycleCurrentSession();
                ep = null;
                ep = repo.Get(ep_id);

                //Expectations
                Assert.IsNotNull(ep);
                Assert.That(ep.EndpointID, Is.EqualTo("EPID"));
                Assert.That(ep.EndpointLatitude, Is.EqualTo(1.0));
                Assert.That(ep.EndpointLongitude, Is.EqualTo(2.0));
                Assert.That(ep.LastStatusUpdate, Is.EqualTo(DateTime.Today));
                Assert.That(ep.Name, Is.EqualTo("EP"));
                Assert.That(ep.NetworkAddress, Is.EqualTo("EP@EP"));
                Assert.That(ep.Status, Is.EqualTo(EndpointStatus.Online));
                Assert.That(ep.StatusNote, Is.EqualTo("Hello, I'm a status note"));
                Assert.That(ep.SupportEmailAddress, Is.EqualTo("hereiam@sonic.net"));
                Assert.That(ep.SupportTelephoneNumber, Is.EqualTo("707-528-7464"));
            }
            finally
            {
                repo.Delete(ep);
            }

        }

        [Test]
        public void CanUpdateExistingManagedEndpoint()
        {
            var ep = CreateNewEndpoint("EPID");

            var repo = new Repository<ManagedEndpoint>();
            repo.SaveOrUpdate(ep);

            try
            {
                int ep_id = ep.Id;
                DataSessionManager.Current.RecycleCurrentSession();

                ep.StatusNote = "Something has changed...";

                repo.SaveOrUpdate(ep);

                DataSessionManager.Current.RecycleCurrentSession();

                ep = null;
                ep = repo.Get(ep_id);

                //Expectation
                Assert.IsNotNull(ep);
                Assert.That(ep.StatusNote, Is.EqualTo("Something has changed..."));
            }
            finally
            {
                repo.Delete(ep);
            }
        }

        [Test]
        public void CanCreateAndPersistEndpointMetricType()
        {
            var metric = new EndpointMetricType
                             {
                                 DataType = MeasurementDataType.Numeric,
                                 CanAggregate = true,
                                 Name = "A Metric",
                                 UnitOfMeasurement = "Hectars"
                             };

            var repo = new Repository<EndpointMetricType>();
            repo.SaveOrUpdate(metric);

            try
            {
                var id = metric.Id;
                metric = null;
                DataSessionManager.Current.RecycleCurrentSession();
                metric = repo.Get(id);

                Assert.IsNotNull(metric);
                Assert.That(metric.DataType, Is.EqualTo(MeasurementDataType.Numeric));
                Assert.That(metric.CanAggregate, Is.EqualTo(true));
                Assert.That(metric.Name, Is.EqualTo("A Metric"));
                Assert.That(metric.UnitOfMeasurement, Is.EqualTo("Hectars"));
            }
            finally
            {
                repo.Delete(metric);
            }
        }

        [Test]
        public void CanCreateAndPersistEndpointPerformanceMeasurement()
        {
            var metricType = new EndpointMetricType();
            var mRepo = new Repository<EndpointMetricType>();
            mRepo.SaveOrUpdate(metricType);
            int metricId = metricType.Id;

            var measurement = new EndpointPerformanceMeasurement
                                  {
                                      MeasurementTime = DateTime.Today,
                                      MetricType = metricType,
                                      NumericValue = 100.0,
                                      TextValue = "hi",
                                      BooleanValue = true
                                  };

            var repo = new Repository<EndpointPerformanceMeasurement>();
            repo.SaveOrUpdate(measurement);

            try
            {
                int id = measurement.Id;
                DataSessionManager.Current.RecycleCurrentSession();

                measurement = repo.Get(id);

                Assert.IsNotNull(measurement);
                Assert.That(measurement.MeasurementTime, Is.EqualTo(DateTime.Today));
                Assert.That(measurement.MetricType.Id, Is.EqualTo(metricId));
                Assert.That(measurement.NumericValue, Is.EqualTo(100.0));
                Assert.That(measurement.TextValue, Is.EqualTo("hi"));
                Assert.That(measurement.BooleanValue, Is.EqualTo(true));
            }
            finally
            {
                mRepo.Delete(metricType);
                repo.Delete(measurement);
            }

        }

        [Test]
        public void CanCreateAndPersistEndpointPerformanceSummary()
        {
            var metricType = new EndpointMetricType();
            new Repository<EndpointMetricType>().SaveOrUpdate(metricType);
            int metricId = metricType.Id;

            var summary = new EndpointPerformanceSummary()
                              {
                                  Average = 1.0,
                                  Max = 2.0,
                                  Min = 3.0,
                                  Metric = metricType,
                                  SampleCount = 100,
                                  SamplePeriodEndTime = DateTime.Today,
                                  SamplePeriodStartTime = DateTime.Today.AddDays(-1),
                                  Sum = 100.0
                              };

            var repo = new Repository<EndpointPerformanceSummary>();
            repo.SaveOrUpdate(summary);

            try
            {
                int id = summary.Id;
                DataSessionManager.Current.RecycleCurrentSession();

                summary = repo.Get(id);

                Assert.IsNotNull(summary);
                Assert.That(summary.Average, Is.EqualTo(1.0));
                Assert.That(summary.Max, Is.EqualTo(2.0));
                Assert.That(summary.Min, Is.EqualTo(3.0));
                Assert.That(summary.Metric.Id, Is.EqualTo(metricId));
                Assert.That(summary.SampleCount, Is.EqualTo(100));
                Assert.That(summary.SamplePeriodEndTime, Is.EqualTo(DateTime.Today));
                Assert.That(summary.SamplePeriodStartTime, Is.EqualTo(DateTime.Today.AddDays(-1)));
                Assert.That(summary.Sum, Is.EqualTo(100));

            }
            finally
            {
                repo.Delete(summary);
            }
        }

        private static ManagedEndpoint CreateNewEndpoint(string endpointId)
        {
            var ep = new ManagedEndpoint
                         {
                             EndpointID = endpointId,
                             EndpointLatitude = 1.0,
                             EndpointLongitude = 2.0,
                             LastStatusUpdate = DateTime.Today,
                             Name = "EP",
                             NetworkAddress = "EP@EP",
                             Status = EndpointStatus.Online,
                             StatusNote = "Hello, I'm a status note",
                             SupportEmailAddress = "hereiam@sonic.net",
                             SupportTelephoneNumber = "707-528-7464"
                         };
            return ep;
        }

    }


}
